iT邦幫忙

2022 iThome 鐵人賽

DAY 10
0
Software Development

歡迎來到 GIS 的世界!30 天從後端開始學 GIS系列 第 10

一起來用 GDAL 處理 Shapefile 吧! - 1 建立

  • 分享至 

  • xImage
  •  

文章同步發表至 Medium

既然有了 DotSpatial 可以處理 Shapefile,為甚麼我還要學習另外兩種工具呢?

神秘的問題

使用 DotSpatial 沒多久之後我就遇到了一個神奇的問題:資料庫的內容一樣,讀取的數量也都一樣,但每個環境:local、STG、Prod 所生產出來的 Shapefile 中,Feature 數量都不一樣。 ?

由於一直研究不出一個原因,所以我選擇改用別的套件,也就是我們接下來要介紹的 GDAL。

準備

.NET Framework 和 .NET Core 所安裝的 Nuget 套件不太相同:

.NET Framework

安裝完下列的套件之後,會自動長出兩個 Configuration 的檔案,只需要保留副檔名是 .cs 的檔案就好,並且加上專案的命名空間就可以開始使用了。

套件名稱 版本
GDAL 3.5.1
GDAL.Native 3.5.1

.NET / .NET Core

如果使用 .NET 安裝上面兩個套件的話,應該在運行時會出現錯誤:

Unable to load DLL 'gdal_wrap' or one of its dependencies

因此 .NET 需要改成安裝 Gdal.Core 才有辦法正常運行。

套件名稱 版本
Gdal.Core 1.0.0

讀取

GDAL 對於 Shapefile 的讀取方式比較完整。之前有提到所有的內容都會寫在 Feature 上,而 Feature 的集合就是一層 Layer,一個 Shapefile 可以擁有多個 Layer。

這裡所讀取的檔案是我另外用 QGIS 建立的,有需要的話可以從 GitHub 上取得。

// 註冊 GDAL
Gdal.AllRegister();
Ogr.RegisterAll();

// 開啟 SHP 檔案(0 - 讀取、1 - 讀寫)
var source = Ogr.Open("test.shp", (int)EnumShapefileOpen.ReadOnly);
var layerCount = source.GetLayerCount();
for (var i = 0; i < layerCount; i++)
{
    // 讀取圖層 Layer 資訊
    var layer = source.GetLayerByIndex(i);
    var fieldCount = layer.GetLayerDefn().GetFieldCount();
    for (var j = 0; j < fieldCount; j++)
    {
        var field = layer.GetLayerDefn().GetFieldDefn(j);
        var fieldName = field.GetName();
        Console.WriteLine($"欄位{j + 1}. {fieldName}");
    }
    
    // 讀取要素 Feature
    Feature feature;
    while ((feature = layer.GetNextFeature()) != null)
    {
        var id = feature.GetFieldAsInteger(0);
        Console.WriteLine($"內容1. Id: {id}");
        
        var name = feature.GetFieldAsString(1);
        Console.WriteLine($"內容2. 土地名稱: {name}");
        
        var area = feature.GetFieldAsInteger64(2);
        Console.WriteLine($"內容3. 土地面積: {area}");
        
        // 轉換成 WKT 的值
        var geometry = feature.GetGeometryRef();
        geometry.ExportToWkt(out var wkt);
        Console.WriteLine($"- WKT: {wkt}");
    }
}

public enum EnumShapefileOpen
{
    ReadOnly
}

執行後的結果如下:

而原本的檔案內容是長這樣:

可以觀察到中文的內容會變成亂碼,但明明欄位的名稱原本也是中文,卻可以好好地顯示。這件事情不是單純改變檔案編碼可以解決的事情,因為需要花一點篇幅解釋,所以會把這個問題的原因和解法放在下一篇。

Reference


上一篇
一起來用 DotSpatial 處理 Shapefile 吧! - 2 建立
下一篇
一起來用 GDAL 處理 Shapefile 吧! - 2 中文亂碼
系列文
歡迎來到 GIS 的世界!30 天從後端開始學 GIS30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言